/************************************************************************
 * Este archivo, representa los metodos necesarios para reflejar los 
 * movimientos de caja realizados en la base de datos
 * 
 * @system: veco-system
 * @description: Sistema de control vehicular
 * @version: 1.0
 * @Copyright © 2013 
 * 
 * @authores:
 * 
 *      > Alberione, Fernando    <falberione_037@gmail.com>
 * 
 *      > Boretto, Martin        <martinboretto@gmail.com>
 * 
 *      > Lenarduzzi, Federico   <fedeatenas@gmail.com>
 * 
 *      > Ocampo, Emanuel        <eocampo86@gmail.com>
 *
 *************************************************************************/

package SistemaCocheras;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;


public class manejadorCaja {

    private Connection conexion = null;
    
    // ---------------------------------------------------------
    // ------- Seccion de constructores de la clase
    // ---------------------------------------------------------     
    
    /**
     * Constructor NO vacio
     */
    public manejadorCaja(Connection c){
        this.conexion = c;
    }

    

    // ---------------------------------------------------------
    // ------- Seccion de metodos publicos auxiliares
    // ---------------------------------------------------------

    /**
     * Funcion encargada de insertar un ingreso de movimiento de caja
     * @param descripcion Representa que tipo de ingreso es
     * @param usuario Representa al usuario que realizo el movimiento
     * @param valor Representa el valor del movimiento
     * @param fecha Representa la fecha en la que se realizo el movimiento
     * @param hora Representa la hora en la que se realizo el movimiento
     * @throws IOException
     * @throws SQLException
     */
    public void insertarIngreso(String descripcion, String usuario, double valor, 
                                String fecha, String hora) throws IOException, SQLException {
        Statement statemen = this.conexion.createStatement();
        String query = "INSERT INTO caja (fecha, dniusuariocaja, hora, descripcion, ingreso) VALUES('"+fecha+"', '"+usuario+"','"+hora+"', '"+descripcion+"','"+valor+"')";
        statemen.executeUpdate(query);
    }// Fin insertarIngreso


    /**
     * Funcion encargada de insertar un egreso de movimiento de caja
     * @param descripcion
     * @param usuario
     * @param valor
     * @param fecha
     * @param hora
     * @throws IOException
     * @throws SQLException
     */
    public void insertarEgreso(String descripcion, String usuario, double valor, String fecha, String hora) throws IOException, SQLException {
        Statement statemen = this.conexion.createStatement();
        String query = "INSERT INTO caja(fecha, dniusuariocaja, hora, descripcion, gasto) VALUES('"+fecha+"', '"+usuario+"', '"+hora+"', '"+descripcion+"','"+valor+"')";
        statemen.executeUpdate(query);
    }// Fin insertarEgreso


    /**
     * Funcion encargada de buscar un movimiento de caja correspondiente a 
     * una fecha determinada
     * @param fecha Representa la fecha del movimiento a retornar
     * @return res
     * @throws IOException
     * @throws SQLException
     */
    public ResultSet buscarPorFecha(String fecha) throws IOException, SQLException {
        manejadorCochera mco = new manejadorCochera(this.conexion);
        ResultSet cochera = mco.buscarCochera();
        ResultSet res = null;
        String hora = "";
        if (cochera.next()){
            // Se obtiene la hora de la base de datos
            hora = cochera.getString ("horainicioperiodo");
        }
        if (!hora.equals("")){
            // Si la hora es valida, se buscan los movimientos de la fecha
            Statement statemen = this.conexion.createStatement();
            String [] parsing = fecha.split("-");
            Calendar fechaAyer = new GregorianCalendar(Integer.parseInt(parsing[0]),
                                                       Integer.parseInt(parsing[1])-1,
                                                       Integer.parseInt(parsing[2]));
            fechaAyer.add(Calendar.DAY_OF_MONTH, -1);
            int anioA = fechaAyer.get(Calendar.YEAR);
            int mesA  = fechaAyer.get(Calendar.MONTH)+1;
            int diaA  = fechaAyer.get(Calendar.DAY_OF_MONTH);
            String fechaDeAyer = anioA+"-"+mesA+"-"+diaA;
            String query =  "SELECT * FROM caja WHERE((fecha = '"+fecha+"' and hora <='"+hora+"')or"
                                                   +"(fecha = '"+fechaDeAyer+"' and hora >'"+hora+"'))";
            res = statemen.executeQuery(query);
        }
        return res;
    }// Fin buscarPorFecha


    /**
     * Funcion encargada de buscar movimientos de caja correspondiente a un
     * usuario en particular
     * @param usuario Representa el usuario al cual se le buscan los movimientos
     * @return res
     * @throws IOException
     * @throws SQLException
     */
    public ResultSet buscarPorUsuario(String usuario) throws IOException, SQLException {
        ResultSet res = null;
        Statement statemen = this.conexion.createStatement();
        String query = "SELECT * FROM caja WHERE(dniusuariocaja = '"+usuario+"')";
        res = statemen.executeQuery(query);
        return res;
    }// Fin buscarPorUsuario


    /**
     * Funcion encargada de buscar movimientos de caja correspondientes a una 
     * fecha determinada de un usuario en particular
     * @param fecha Representa la fecha del movimiento
     * @param usuario Representa el usuario interviniente en la fecha del movimiento
     * @return res
     * @throws IOException
     * @throws SQLException
     */
    public ResultSet buscarPorFechaYUsuario(String fecha, String usuario) throws IOException, SQLException {
        Statement statemen = this.conexion.createStatement();
        // Se obtiene la hora del periodo
        manejadorCochera mco = new manejadorCochera(this.conexion);
        ResultSet cochera = mco.buscarCochera();
        String hora = "";
        if (cochera.next()){
            hora = cochera.getString ("horainicioperiodo");
        }
        String [] parseHora = hora.split(":");
        int horaInt = Integer.parseInt(parseHora[0]);
        int minInt = Integer.parseInt(parseHora[1]);
        int segInt = Integer.parseInt(parseHora[2]);
        // Se obteniene la hora actual 
        manejadorEstadia me = new manejadorEstadia(this.conexion);
        String horaActual = me.calcularHora();
        String [] parseHoraActual = horaActual.split(":");
        int hsActual = Integer.parseInt(parseHoraActual[0]);
        int minActual = Integer.parseInt(parseHoraActual[1]);
        int segActual = Integer.parseInt(parseHoraActual[2]);
        ResultSet res = null;
        if (((horaInt < hsActual) || ((horaInt == hsActual) && (minInt < minActual))||
            ((horaInt == hsActual) && (minInt == minActual) && segInt <= segActual)) && (hsActual <= 23)){
            String query =  "SELECT * FROM caja WHERE(fecha = '"+fecha+"' and hora >='"+hora+
                            "' and dniusuariocaja = '"+usuario+"')";
            res = statemen.executeQuery(query);
        }
        else{
            res = buscarPorFecha(usuario, fecha, hora, "", statemen);
        }
        return res;
    }// Fin buscarPorfechaYUsuario
    
    
    /**
     * 
     * @param con
     * @param fecha
     * @return
     * @throws IOException
     * @throws SQLException
     */
    public ResultSet buscarPorFechaAdministrador(String fecha) throws IOException, SQLException {
        Statement statemen = this.conexion.createStatement();
        // Se obtiene la hora del periodo
        manejadorCochera mco = new manejadorCochera(this.conexion);
        ResultSet cochera = mco.buscarCochera();
        String hora = "";
        if (cochera.next()){
            hora = cochera.getString ("horainicioperiodo");
        }
        String [] parseHora = hora.split(":");
        int horaInt = Integer.parseInt(parseHora[0]);
        int minInt = Integer.parseInt(parseHora[1]);
        int segInt = Integer.parseInt(parseHora[2]);
        // Se obtiene la hora actual
        manejadorEstadia me = new manejadorEstadia(this.conexion);
        String horaActual = me.calcularHora();
        String [] parseHoraActual = horaActual.split(":");
        int hsActual = Integer.parseInt(parseHoraActual[0]);
        int minActual = Integer.parseInt(parseHoraActual[1]);
        int segActual = Integer.parseInt(parseHoraActual[2]);
        ResultSet res = null;
        if (((horaInt < hsActual) || ((horaInt == hsActual) && (minInt < minActual)) || 
             ((horaInt == hsActual) && (minInt == minActual) && segInt <= segActual)) && (hsActual <= 23)){
            String query =  "SELECT * FROM caja WHERE(fecha = '"+fecha+"' and hora >='"+hora+"')";
            res = statemen.executeQuery(query);
        }
        else{
            res = buscarPorFecha("", fecha, hora, horaActual, statemen);
        }
        return res;
    }// Fin buscarPorfechaAdministrador
    
    
    /**
     * Funcion encargada de realizar el arqueo de caja creando los directorios
     * correspondientes a anio, mes y usuario interviniente en la ruta 
     * predeterminada del disco
     * @param tipoDeArqueo Representa el tipo de arqueo de caja a realizar
     * @param datos Representan los datos del arqueo de caja
     * @param usuario Representa el usuario interviniente en el arqueo
     * @return arqueoFinal
     * @throws SQLException
     */
    public String hacerArqueoDeCaja (String tipoDeArqueo, ResultSet datos, String usuario) throws SQLException{
        manejadorEstadia me = new manejadorEstadia(this.conexion);
        String ruta = "D:\\Arqueos de Cajas - B&B\\";
        File dir = new File(ruta);
        String arqueoFinal = "";
        if(!dir.exists()){ 
            // Si no existe creo el directorio
            if(dir.mkdir()){ 
                // Directorio creado correctamente
                System.out.println("La carpeta se ha creado");
            }
            else{
                // Error al crear el directorio
                System.out.println("La carpeta NO ha creado");
            }
        }
        String anioCorriente = "";
        String mesCorriente = "";
        String fechaCorriente[];
        fechaCorriente = me.calcularFecha().split("-");
        anioCorriente = fechaCorriente[0];
        // Se filtra el mes (en string) correspondiente a la fecha corriente
        mesCorriente = filtrarMesCorriente(fechaCorriente[1]);
        // Se crea el directorio y subdirectorio para guardar la informacion de movimientos
        ruta = crearDirectorioYSubdirectorios(ruta, anioCorriente, mesCorriente, dir, me, usuario);
        try {
            FileWriter fw = new FileWriter(ruta, false);
            arqueoFinal = generarContenido(tipoDeArqueo, datos);
            fw.write(arqueoFinal);  //Escritura de la informacion en el archivo
            fw.close(); //Se cierra el archivo
        } 
        catch (IOException ex) {
            System.out.println("Error al crear el archivo!!");
        }        
        return arqueoFinal;
    }// Fin hacerArqueoDeCaja
    

    
    // ---------------------------------------------------------
    // ------- Seccion de metodos privados
    // ---------------------------------------------------------    
    
    /**
     * Funcion encargada de buscar un movimiento de caja correpondiente a 
     * una fecha y a un usuario o administrador determiando
     * @param usuario Representa el usuario interviniente en el movimiento
     * @param fecha Representa la fecha en la que se realizo el movimiento
     * @param hora Representa la hora del movimiento
     * @param statement Representa el statement de la conexion 
     * @return resultado
     * @throws SQLException 
     */
    private ResultSet buscarPorFecha(String usuario, String fecha, String hora, String horaActual, 
                                     Statement statement) throws SQLException{
        ResultSet resultado = null;
        String [] parsing = fecha.split("-");
        Calendar fechaAyer = new GregorianCalendar(Integer.parseInt(parsing[0]),
                                                        Integer.parseInt(parsing[1])-1,
                                                        Integer.parseInt(parsing[2]));
        fechaAyer.add(Calendar.DAY_OF_MONTH, -1);
        int anioA = fechaAyer.get(Calendar.YEAR);
        int mesA  = fechaAyer.get(Calendar.MONTH)+1;
        int diaA  = fechaAyer.get(Calendar.DAY_OF_MONTH);
        String fechaDeAyer = anioA+"-"+mesA+"-"+diaA;
        if(usuario.compareTo("") == 0){
            // Se busca por administrador
            String query =  "SELECT * FROM caja WHERE((fecha = '"+fecha+"' and hora <='"+horaActual+"')or"
                                                   +"(fecha = '"+fechaDeAyer+"' and hora >'"+hora+"'))";
            resultado = statement.executeQuery(query);
        }
        else{
            // Se busca por usuario
            String query =  "SELECT * FROM caja WHERE(((fecha = '"+fecha+"' and hora <='"+hora+"')or"
                                                   +"(fecha = '"+fechaDeAyer+"' and hora >'"+hora+"'))"
                            + " and dniusuariocaja = '"+usuario+"')";
            resultado = statement.executeQuery(query);
        }
        return resultado;        
    }// Fin buscarPorFecha
    
    
    /**
     * Funcion encargada de filtrar el mes corriente (en string) de acuerdo a la
     * fecha pasado como parametro
     * @param fechaC Representa la fecha corriente
     * @return mesCorriente
     */
    private String filtrarMesCorriente(String fechaC){
        String mesCorriente = "";
        int mes = Integer.parseInt(fechaC);
        switch(mes){
            case (1): mesCorriente = "Enero";
                      break;
            case (2): mesCorriente = "Febrero";
                      break;
            case (3): mesCorriente = "Marzo";
                      break;
            case (4): mesCorriente = "Abril";
                      break;
            case (5): mesCorriente = "Mayo";
                      break;
            case (6): mesCorriente = "Junio";
                      break;
            case (7): mesCorriente = "Julio";
                      break;
            case (8): mesCorriente = "Agosto";
                      break;
            case (9): mesCorriente = "Septiembre";
                      break;
            case (10): mesCorriente = "Octubre";
                      break;
            case (11): mesCorriente = "Noviembre";
                      break;
            case (12): mesCorriente = "Diciembre";
                      break;
        }
        return mesCorriente;
    }// Fin filtrarMesCorriente
    
    
    /**
     * Funcion encargada de generar el directorio y los subdirectorios
     * correspondientes a anio y mes de movimientos de caja
     * @param ruta Representa la ruta en donde se va a crear el directorio
     * @param anioC Representa el anio corriente
     * @param mesC Representa el mes corriente
     * @param dir Representa el directorio a crear
     * @param me Representa el manejar de estadia para calcular la fecha
     * @param usuario Representa el usuario interviniente en el movimiento
     */
    private String crearDirectorioYSubdirectorios(String ruta, String anioC, String mesC, File dir,
                                                manejadorEstadia me, String usuario){
        String rutaAux = "";
        // Se crea el subdirectorio del año corriente
        rutaAux += ruta; 
        rutaAux += anioC+"\\";     
        dir = new File(rutaAux);
        if(!dir.exists()){ 
            // Si no existe creo el directorio
            if(dir.mkdir()) {
                // Directorio creado correctamente
                System.out.println("La carpeta se ha creado");
            }
            else{
                // Error al crear el directorio
                System.out.println("La carpeta NO ha creado");
            }
        }
        rutaAux += mesC+"\\";      
        // Se crea el subdirectorio del mes corriente
        dir = new File(rutaAux);
        if(!dir.exists()){ // Si no existe creo el directorio
            if(dir.mkdir()) // Directorio creado correctamente
                System.out.println("La carpeta se ha creado");
            else// Error al crear el directorio
                System.out.println("La carpeta NO ha creado");
        }
        rutaAux += me.calcularFecha()+"\\";
        dir = new File(rutaAux);
        if(!dir.exists()){ 
            // Si no existe creo el directorio
            if(dir.mkdir()){
                // Directorio creado correctamente
                System.out.println("La carpeta se ha creado");
            }
            else{
                // Error al crear el directorio
                System.out.println("La carpeta NO ha creado");
            }
        }
        rutaAux += me.calcularFecha()+"_"+usuario+".txt";
        File file = new File(rutaAux);
        if(!file.exists()){ 
            // Si no existe creo el directorio
            try {
                RandomAccessFile archivo = new RandomAccessFile( file, "rw" );
                archivo.close();
            } 
            catch (Exception e){
                System.out.println ("Ha ocurrido un error al crear el arcihvo.");
            }
        }
        return rutaAux;
    }// Fin crearDirectorioYSubdirectorios
    
    
    /**
     * Funcion encargada de generar el contenido del ticket en formato string
     * @param tipoDeArqueo Representa el tipo de arqueo de caja a realizar
     * @param datos Representa los datos que seran generados en el ticket
     * @return resultado
     * @throws SQLException 
     */
    private String generarContenido(String tipoDeArqueo, ResultSet datos) throws SQLException {
        Set<String> usuarios = new HashSet();
        int estadiasDeVehiculos = 0;
        int cobrosACliente = 0;
        Double montoTotalPorEstadias = 0.0;
        Double montoTotalPorPagosDeCliente = 0.0;
        Double montoTotalDeIngresos = 0.0;
        Double montoTotalGastos = 0.0;
        String fecha = "";
        try {
            while (datos.next()) {
                usuarios.add(datos.getString(2));
                fecha = datos.getString(1);
                if (datos.getString(4) != null){
                    String ingreso = datos.getString(4);
                    montoTotalDeIngresos += Double.parseDouble(ingreso);
                    if (datos.getString(3).equals("Estadia de Vehiculo")){
                        montoTotalPorEstadias += Double.parseDouble(ingreso);
                        estadiasDeVehiculos += 1;
                    }
                    if (datos.getString(3).equals("Pago de Cliente")){
                        montoTotalPorPagosDeCliente += Double.parseDouble(ingreso);
                        cobrosACliente += 1;
                    }
                }
                else{
                    String egreso = datos.getString(5);
                    montoTotalGastos += Double.parseDouble(egreso);
                }
            }
        } 
        catch (SQLException ex) {
            System.out.println("Se ha producido un error al generar el contenido del ticket...");
        }
        String resultado =  "Sistema de Cocheras B&B \r\n" +
                            "\r\n" +
                            "Arqueo de Caja tipo : "+tipoDeArqueo+"\r\n"+
                            "\r\n" +
                            "Periodo : "+fecha+"\r\n"+
                            "\r\n" +
                            "Usuarios intervinientes: \r\n" ;
                            Iterator iter = usuarios.iterator();
                            ResultSet usuario = null;
                            manejadorUsuarioAdmin mua = new manejadorUsuarioAdmin(this.conexion);
                            while (iter.hasNext()){
                                String dni = iter.next().toString();
                                usuario = mua.buscarUsuarioAdmin(dni);
                                usuario.next();
                                resultado += "                       "+usuario.getString("nombre")+" "+usuario.getString("apellido")+" ("+usuario.getString("dniusuario")+")\r\n" ;
                            }
                resultado += "\r\n" +
                            "-----------------------------------------------------------------------------------" +
                            "\r\n" +
                            "INGRESOS:\r\n" +
                            "\r\n" +
                            "   Numero de Estadias del periodo (incluido Clientes): "+estadiasDeVehiculos+"\r\n" +
                            "\r\n" +
                            "   Monto total de Ingresos por Estadias de Vehiculos : $"+montoTotalPorEstadias+"\r\n" +
                            "\r\n" +
                            "   Numero de pagos de Clientes : "+cobrosACliente+"\r\n" +
                            "\r\n" +
                            "   Monto total de Ingresos por pagos de Clientes : $"+montoTotalPorPagosDeCliente+"\r\n" +
                            "\r\n" +
                            "   Total de ingresos : $"+montoTotalDeIngresos+"\r\n" +
                            "\r\n" +
                            "\r\n" +
                            "-----------------------------------------------------------------------------------" +
                            "\r\n" +
                            "EGRESOS:\r\n" +
                            "\r\n" +
                            "   Total de Egresos : $"+montoTotalGastos+"\r\n" +
                            "\r\n" +
                            "\r\n" +
                            "-----------------------------------------------------------------------------------" +
                            "\r\n" +
                            "INGRESO NETO DEL PERIODO : $"+(montoTotalDeIngresos-montoTotalGastos) ;
        return resultado;
    }// Fin generarContenido
    
}// Fin clase manejadorCaja
